//-----------------------------------------------------------------------
// <copyright file="TupleStore.cs" company="tuliprules.org">
//     Copyright (c) 2010 tuplelister, tuliprules.org.
// </copyright>
// <summary>This is the TupleStore class.</summary>
//-----------------------------------------------------------------------

namespace Tulip.Engine.Tuples
{
    using System;
    using System.Collections.Generic;

    /// <summary>
    /// The TupleStore is a core feature of the rules engine, and serves as the working memory of the production system.
    /// It manages 'tuples'. 
    /// </summary>
    public static class TupleStore
    {
        /// <summary>
        /// Collection of all tuple view groups.
        /// </summary>
        private static readonly Dictionary<TupleStoreSession, Dictionary<int, ITupleRelation>> TupleRelationsAll = new Dictionary<TupleStoreSession, Dictionary<int, ITupleRelation>>();

        /// <summary>
        /// Clears all tuples from the tuple store.
        /// </summary>
        /// <param name="tupleStoreSession">The current tuple store session.</param>
        public static void Clear(TupleStoreSession tupleStoreSession)
        {
            foreach (var tr in GetTupleRelations(tupleStoreSession).Values)
            {
                tr.ClearAllTuples();
            }

            TupleRelationsAll.Remove(tupleStoreSession);
        }

#pragma warning disable 1587
        /// <summary>
        /// Creates and registers a new tuple relation for a given TupleStoreSession.   If the tuple view
        /// group already exists, no action is taken.
        /// </summary>
        /// <param name="tupleRelationId">Id of the tuple relation.</param>
        /// <param name="tupleStoreSession">The tupleStore session to which the tuple relation will be assigned.</param>
        /// <typeparam name="TTuple">The tuple type.</typeparam>
        /// <returns>The registered tuple relation.</returns>
#if MONO201_COMPLIANT
        public static ITupleRelation<TTuple> RegisterTupleRelation<TTuple>(int trId, TupleStoreSession tupleStoreSession) 
#else
        public static ITupleRelation<TTuple> RegisterTupleRelation<TTuple>(int tupleRelationId, TupleStoreSession tupleStoreSession) where TTuple : Tuple
#endif
#pragma warning restore 1587
        {
            var tupleRelations = GetTupleRelations(tupleStoreSession);

            var tupleRelType = typeof(TupleRelation<Tuple>);
            var t = tupleRelType.Namespace + "." + tupleRelType.Name;
            var generic = Type.GetType(t).MakeGenericType(typeof(TTuple));

            // Create BSG via reflection in order to create required type
            var tupleRelation = (ITupleRelation)Activator.CreateInstance(generic, tupleRelationId);

            tupleRelations.Add(tupleRelationId, tupleRelation);

            return (ITupleRelation<TTuple>)tupleRelation;
        }

        /// <summary>
        /// Obtains a tuple store session.
        /// </summary>
        /// <param name="sessionIdentifier">Identifies a rule set for which the tupleStore session will be used.</param>
        /// <returns>A tuple store session.</returns>
        public static TupleStoreSession GetTupleStoreSession(string sessionIdentifier)
        {
            return new TupleStoreSession(sessionIdentifier);
        }

        /// <summary>
        /// Obtains a tupleStore session.
        /// </summary>
        /// <returns>A tuple store session.</returns>
        public static TupleStoreSession GetTupleStoreSession()
        {
            // Create a session identifier.
            return new TupleStoreSession(Guid.NewGuid().ToString());
        }

        /// <summary>
        /// Returns a tuple relation for a given tupleStore session.
        /// </summary>
        /// <param name="tupleRelationId">The identifier of the tuple relation.</param>
        /// <param name="tupleStoreSession">The tupleStore session that contains the tuple relation.</param>
        /// <returns>The tuple relation for the given tupleStore session.</returns>
        public static ITupleRelation<Tuple> GetTupleRelation(int tupleRelationId, TupleStoreSession tupleStoreSession)
        {
            return (ITupleRelation<Tuple>)GetTupleRelations(tupleStoreSession)[tupleRelationId];
        }

        /// <summary>
        /// Reset the tupleStore.
        /// </summary>
        public static void Reset()
        {
            TupleRelationsAll.Clear();
            TuplePool.Clear();
        }

        /////////// <summary>
        /////////// Reset a given session within the tupleStore.
        /////////// </summary>
        /////////// <param name="tupleStoreSession">The session to be reset.</param>
        ////////internal static void Reset(TupleStoreSession tupleStoreSession)
        ////////{
        ////////    Dictionary<int, ITupleRelation> tupleRelations;

        ////////    if (tupleRelationsAll.TryGetValue(tupleStoreSession, out tupleRelations))
        ////////    {
        ////////        tupleStoreSession.Reset();
        ////////        tupleRelations.Clear();
        ////////    }
        ////////}

        /// <summary>
        /// Returns the collection of tuple view groups for a given tupleStore session.
        /// </summary>
        /// <param name="tupleStoreSession">The tupleStore session whose collections of tuple view groups is to be returned.</param>
        /// <returns>The collection of tuple view groups for the given tupleStore session.</returns>
        private static Dictionary<int, ITupleRelation> GetTupleRelations(TupleStoreSession tupleStoreSession)
        {
            Dictionary<int, ITupleRelation> tupleRelations;

            if (!TupleRelationsAll.TryGetValue(tupleStoreSession, out tupleRelations))
            {
                // Create a new tuple relation collection for this tupleStore session
                tupleRelations = new Dictionary<int, ITupleRelation>();
                TupleRelationsAll.Add(tupleStoreSession, tupleRelations);
            }

            return tupleRelations;
        }
    }
}